
/* <primitive: 1>
 * <SmallInteger> + <SmallInteger>
 * Answer the argument added to the receiver. Fail if the receiver, argument or result is not a SmallInteger.
 * Essential.
 */
void primAdd()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	int ans = packSmInt(a+b);
	
	if(success) popNandPush(2, ans);
}


/* <primitive: 2>
 * <SmallInteger> - <SmallInteger>
 * Answer the argument subtracted from the receiver. Fail if the receiver, argument or result is not a SmallInteger.
 * Essential.
 */
void primSubtract()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	int ans = packSmInt(a-b);
	
	if(success) popNandPush(2, ans);
}

/* <primitive: 3>
 * <SmallInteger> < <SmallInteger>
 * Answer true if the receiver is less than the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primLessThan()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a < b ? true : false );
}

/* <primitive: 4>
 * <SmallInteger> > <SmallInteger>
 * Answer true if the receiver is greater than the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primGreaterThan()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a > b ? true : false );
}

/* <primitive: 5>
 * <SmallInteger> <= <SmallInteger>
 * Answer true if the receiver is less than or equal to the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primLessOrEqual()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a <= b ? true : false );
}

/* <primitive: 6>
 * <SmallInteger> >= <SmallInteger>
 * Answer true if the receiver is greater than or equal to the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primGreaterOrEqual()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a >= b ? true : false );
}

/* <primitive: 7>
 * <SmallInteger> = <SmallInteger>
 * Answer true if the receiver is equal to the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primEqual() //This primitive must pre-date the idea for tagged pointer representation, or SmallIntegers would just use primIdentical
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a == b ? true : false );
}

/* <primitive: 8>
 * <SmallInteger> ~= <SmallInteger>
 * Answer true if the receiver is not equal to the argument, false otherwise. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primNotEqual()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if(success) popNandPush(2, a != b ? true : false );
}

/* <primitive: 9>
 * <SmallInteger> * <SmallInteger>
 * Answer the receiver multipled by the receiver. Fail if the receiver, argument or result is not a SmallInteger.
 * Essential.
 */
void primMultiply()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	int ans = a*b;
	
	if(!( b==0 || ans/b==a )) success = 0; //un-invertable => overflow
	
	ans = packSmInt(ans);
	if(success) popNandPush(2, ans);
}


/* <primitive: 10>
 * <SmallInteger> / <SmallInteger>
 * Answer the receiver divided by the receiver. Exact division.  Fail if the receiver, argument or result is not a SmallInteger.
 * Essential.
 */
void primDivide()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if( b==0 || a%b!=0 ) success = 0; //divide by zero or inexact division
	else
	{
		int ans = packSmInt(a/b);
		if(success) popNandPush(2, ans);
	}
}
 
/* <primitive: 11>
 * <SmallInteger> \\ <SmallInteger>
 * Answer the remainder of division rounded towards negative infinity. Fail if the argument is zero or the receiver or argument is not a SmallInteger.
 * Optional.
 */
void primMod()
{
	//unimplemented, fail
	success = 0;
}
 
/* <primitive: 12>
 * <SmallInteger> // <SmallInteger>
 * Answer the receiver divided by the argument rounded towards negative infinity. Fail if the argument is zero or the receiver or argument is not a SmallInteger.
 * Optional.
 */
void primDiv()
{
	int rcvr = unpackSmInt(peek(1));
	int arg = unpackSmInt(peek(0));

	if( arg==0 ) success = 0; //division by zero fails
	else
	{
		/* from VMMaker */
		int posArg, posRcvr, result;
		if(rcvr > 0)
		{
			if(arg > 0) result = rcvr / arg;
			else {
				posArg = 0 - arg;
				result = 0 - ((rcvr + (posArg - 1)) / posArg);
			}
		}else{
			posRcvr = 0 - rcvr;
			if( arg > 0 ) result = 0 - ((posRcvr + (arg - 1)) / arg);
			else{
				posArg = 0 - arg;
				result = posRcvr / posArg;
			}
		}
		
		result = packSmInt(result);
		if(success) popNandPush(2, result);
	}
}

/* <primitive: 13>
 * <SmallInteger> quo: <SmallInteger>
 * Answer the remainder of division rounded towards zero. Fail if the argument is zero or the receiver or argument is not a SmallInteger.
 * Optional.
 */
void primQuo()
{
	int rcvr = unpackSmInt(peek(1));
	int arg = unpackSmInt(peek(0));
		
	if( arg==0 ) success = 0; //division by zero fails
	else
	{
		/* from VMMaker */
		int result;
		if(rcvr > 0)
		{
				if(arg > 0) result = rcvr / arg;
				else result = 0 - (rcvr / (0-arg));
		} else {                
				if(arg > 0) result = 0 - ((0 - rcvr) / arg);
				else result = (0 - rcvr) / (0 - arg);
		}
		
		result = packSmInt(result);
		if(success) popNandPush(2, result);
	}
}

/* <primitive: 14>
 * <SmallInteger> bitAnd: <SmallInteger>
 * Answer the bit wise AND of the receiver and the argument, interpretered in 2's complement representation. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primBitAnd()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
    int c = packSmInt( a & b ); //BOGUS Can this fail?
	
	if(success) popNandPush(2, c);
}

/* <primitive: 15>
 * <SmallInteger> bitOr: <SmallInteger>
 * Answer the bit wise OR of the receiver and the argument, interpretered in 2's complement representation. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primBitOr()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
    int c = packSmInt( a | b ); //BOGUS Can this fail?
	
	if(success) popNandPush(2, c);
}

/* <primitive: 16>
 * <SmallInteger> bitXor: <SmallInteger>
 * Answer the bit wise XOR of the receiver and the argument, interpretered in 2's complement representation. Fail if the receiver or argument is not a SmallInteger.
 * Essential.
 */
void primBitXor()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
    int c = packSmInt( a ^ b ); //BOGUS Can this fail?  Does this make sense for negative values?
	
	if(success) popNandPush(2, c);
}

/* <primitive: 17>
 * <SmallInteger> bitShift: <SmallInteger>
 * Answer the receiver (interpretered in 2's complement representation) shifted left by the number of bits indicated by the receiver. Fail if the receiver, argument or result is not a SmallInteger.
 * Essential.
 */
void primBitShift()
{
	int a = unpackSmInt(peek(1));
	int b = unpackSmInt(peek(0));
	
	if( b < 0 ) { //Ok to lose bits shifting right
		
		int shifted = packSmInt( a >> -b );
		if(success) popNandPush(2, shifted);
		
	} else {
		int shifted = a << b; 
		if(shifted >> b != a) success=0; //check for lost bits by seeing if computation is reversible
        else
		{
			shifted = packSmInt(shifted);
			if(success) popNandPush(2, shifted);
		}
	}
}

/* <primitive: 18>
 * <Number> @ <Number>
 * Shortcut for Point x: receiver y: argument
 * Optional.
 */
void primMakePoint()
{
	//Fail
	success = 0;
}

